#ifndef FIELD_H
#define FIELD_H

#include <QObject>
#include <QVariant>
#include <QMetaType>

#include <QTime>
#include <QDebug>
#define DP qDebug()
#define DF DP << __FUNCTION__
#define DT DP << QTime::currentTime().toString("hh:mm:ss.zzz")

namespace QyOrm {

class Table;

enum class FieldType{Foreign, String, Integer, Double, DateTime, Boolean};

class Field : public QObject
{
    Q_OBJECT
public:
    Field();
    Field(const Field&);
    QString createTemplate();
    void setTable(Table *table);
public:
    virtual QString select() = 0;
    virtual QString createType() = 0;
    virtual QString create();
    virtual QString execute();
    virtual bool isString();
    virtual void query(const QVariant& var) = 0;
public:
    Table* table = nullptr;
    QString fieldName;
    bool primaryKey = false;
    bool unique = false;
    bool notNull = false;
    Field* self = nullptr;
    FieldType fieldType;
public:
    bool isNull = true;
signals:
    void modify();
};

class ForeignField: public Field
{
public:
    ForeignField();
    QString select();
    QString createType();
    void query(const QVariant& var);
public:
    Table* get() const;
    template<class T>T* get();
    bool set(Table *value, bool isWild = false);//isWild-表示value是否需要指定parent
public:
    ForeignField& operator() ();
    ForeignField& operator=(const ForeignField&);
    ForeignField& operator=(Table* value);
private:
    Table* data = nullptr;
};

template<class T>
T *ForeignField::get()
{
    return dynamic_cast<T*>(get());
}

class StringField : public Field
{
public:
    StringField();
    QString select();
    QString createType();
    void query(const QVariant& var);
    bool isString();
public:
    QString get() const;
    bool set(const QString &value);
public:
    StringField& operator() ();
    StringField& operator=(const StringField&);
    StringField& operator=(const QString&);
private:
    QString data;
};

class IntegerField : public Field
{
public:
    IntegerField();
    QString select();
    QString createType();
    void query(const QVariant& var);
public:
    int32_t get() const;
    bool set(const int32_t &value);
public:
    IntegerField& operator() ();
    IntegerField& operator=(const IntegerField&);
    IntegerField& operator=(const int32_t&);
private:
    int32_t data;
};

class DoubleField : public Field
{
public:
    DoubleField();
    QString select();
    QString createType();
    void query(const QVariant& var);
public:
    double get() const;
    bool set(const double &value);
public:
    DoubleField& operator() ();
    DoubleField& operator=(const DoubleField&);
    DoubleField& operator=(const double&);
private:
    double data;
};

#define datetime_format "yyyy-MM-dd hh:mm:ss"
class DateTimeField : public Field
{
public:
    DateTimeField();
    QString select();
    QString createType();
    void query(const QVariant& var);
public:
    QDateTime get() const;
    bool set(const QDateTime &value);
public:
    DateTimeField& operator() ();
    DateTimeField& operator=(const DateTimeField&);
    DateTimeField& operator=(const QDateTime&);
private:
    QDateTime data;
};

class BooleanField : public Field
{
public:
    BooleanField();
    QString select();
    QString createType();
    void query(const QVariant& var);
public:
    bool get() const;
    bool set(const bool &value);
public:
    BooleanField& operator() ();
    BooleanField& operator=(const BooleanField&);
    BooleanField& operator=(const bool&);
private:
    bool data;
};

}

Q_DECLARE_METATYPE(QyOrm::ForeignField)
Q_DECLARE_METATYPE(QyOrm::StringField)
Q_DECLARE_METATYPE(QyOrm::IntegerField)
Q_DECLARE_METATYPE(QyOrm::DoubleField)
Q_DECLARE_METATYPE(QyOrm::DateTimeField)
Q_DECLARE_METATYPE(QyOrm::BooleanField)

#endif // FIELD_H
